#include "FUNCTIONS.h"



// 将字符串转换为JSON格式
Json::Value Functions::stringToJson(const std::string& str) {
    Json::Value jsonValue;
    Json::Reader reader;

    if (!reader.parse(str, jsonValue)) {
        std::cerr << "Failed to parse JSON data." << std::endl;
    }

    return jsonValue;
}

// 将JSON格式转换为字符串
std::string Functions::jsonToString(const Json::Value& jsonValue) {
    Json::StreamWriterBuilder writer;
    return Json::writeString(writer, jsonValue);
}

void Functions::sln_bin2str(
    char *str,
    unsigned char *ptr,
    int len)
{
    char tmp[4];
    int i;

    // 转十六进制字符串
    str[0] = '\0';
    for (i = 0; i < len; i++)
    {

        sprintf(tmp, "%02x", ptr[i]);
        strcat(str, tmp);
    }
}

std::string Functions::unsignedCharArrayToString(const unsigned char *array, size_t length)
{
    std::string result;
    for (size_t i = 0; i < length; i++)
    {
        result += static_cast<char>(array[i]);
    }
    return result;
}

//发送get请求用到的回调函数
size_t Functions::my_write_callback(char* ptr, size_t size, size_t nmemb, std::string* stream) {
    size_t data_size = size * nmemb;
    stream->append(ptr, data_size);
    return data_size;
}

// 发送GET请求并解析JSON数据
Json::Value Functions::send_get_request(const std::string& url) {
    CURL* curl;
    CURLcode res;
    std::string response;

    curl = curl_easy_init();         //创建一个curl句柄,即一个用于执行单个URL传输的对象。它返回一个指向CURL句柄的指针。后续的libcurl函数将使用该句柄来设置和执行请求
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());       //这个函数用于设置要请求的URL。CURLOPT_URL是一个常量，表示设置URL选项，url是一个字符串
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_write_callback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);   //这个函数用于给回调函数传递参数,服务器返回数据可以存入该参数中
        res = curl_easy_perform(curl);                          //这个函数用于执行URL传输。之前设置的URL、回调函数等参数将被使用来发起GET请求，并将响应数据通过回调函数处理。
        curl_easy_cleanup(curl);
        if (res != CURLE_OK) {
            std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
        }
        

        //提纯响应字符串中的json
        std::string jsonBody = extractJsonData(response);

        // 解析JSON数据
        Json::Value root;                                       //Json::Value 是jsoncpp库中表示JSON值的类型，可以表示一个JSON对象、数组、字符串等。这里的root用来存放解析后的json数据
        Json::Reader reader;                                    //这里定义了一个 Json::Reader 对象，用于解析JSON字符串。Json::Reader 是jsoncpp库中的解析器，用于将JSON字符串解析为Json::Value对象。
        bool parsingSuccessful = reader.parse(jsonBody, root);  //parse函数将json字符串response解析为json对象存入root
        if (parsingSuccessful) {
            std::cout << "JSON Data received:" << std::endl;
            std::cout << root << std::endl;
            return root;
        }
        else {
            std::cerr << "Failed to parse JSON data." << std::endl;
        }
    }
    return Json::Value(); // Return empty Json::Value if the request fails
}

// 发送 POST 请求并包含 JSON 数据 
Json::Value Functions::send_post_request(const std::string& url, const std::string& json_data) {
    std::cout << "进入send——post函数" << std::endl;
    CURL* curl;
    CURLcode res;
    std::string response;

    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_POST, 1L);
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_data.c_str());

        struct curl_slist* headers = NULL;
        headers = curl_slist_append(headers, "Content-Type: application/json");
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_write_callback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);   //这个函数用于给回调函数传递参数,服务器返回数据可以存入该参数中
        
        res = curl_easy_perform(curl);

        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
        
        if (res != CURLE_OK) {
            std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
            std::cout <<"退出send——post函数" << std::endl;
            return Json::Value();
        }

        
        //提纯响应字符串中的json
        std::string jsonBody = extractJsonData(response);

        std::cout << "send——post4" << std::endl;

        // 解析JSON数据
        Json::Value root;                                       
        Json::Reader reader;                                    
        bool parsingSuccessful = reader.parse(jsonBody, root);
        if (parsingSuccessful) {
            std::cout << "JSON Data received:" << std::endl;
            std::cout << root << std::endl;
            std::cout <<"退出send——post函数" << std::endl;
            return root;
        }
        else {
            std::cerr << "Failed to parse JSON data." << std::endl;
        }
    }
    std::cout <<"退出send——post函数" << std::endl;
    return Json::Value(); // Return empty Json::Value if the request fails
}

//*******************************************************************************************************************************************************************************

Json::Value Functions::processCidAndGetRid(const std::string& cid) {
    // 构建GET请求URL
    std::string url = SERVER_IP + "/get_route_id_mac_ifn_from_cid?cid=" + cid;

    // 发送GET请求并解析JSON数据
    Json::Value response = send_get_request(url);       
    // 在此处处理 JSON 数据并返回 rid
    std::string err_no = response["err_no"].asString(); //提取错误码,如1则报错
    if (err_no == "1") {
        std::cout << "processcid:未查询到该cid相应信息 或多维标识不完整" << std::endl;
        Json::Value result;
        result["err_no"] = 1;
        return result;
    }
    else if(err_no == "0"){
        std::string rid = response["route_id"].asString();
        std::string mac = response["mac"].asString();       //更新:在查询rid的函数中同时查一下mac地址和ifn,供demo使用
        std::string ifn = response["ifn"].asString();
        std::string service_id = response["service_id"].asString();
        Json::Value result;
        result["rid"] = rid;
        result["mac"] = mac;
        result["ifn"] = ifn;
        result["service_id"] = service_id;
        result["err_no"] = 0;
        return result;
    }
    else {
        std::cout << "请求数据有未知错误!" << std::endl;
        return "NULL"; }
}

std::string Functions::processRidAndGetCid(const std::string& rid) {
    // 构建GET请求URL
    std::string url = SERVER_IP + "/get_cid_from_route_id?route_id=" + rid;

    // 发送GET请求并解析JSON数据
    Json::Value response = send_get_request(url);       //没写完,需要处理返回的json格式response,根据返回值判断是否成功并提取出cid
    // 在此处处理 JSON 数据并返回 cid
    std::string err_no = response["err_no"].asString(); //提取错误码,如1则报错
    if (err_no == "1") {
        std::cout << "未查询到该rid相应cid!" << std::endl;
        return "NULL";
    }
    else if (err_no == "0") {
        std::string cid = response["cid"].asString();
        return cid;
    }
    else {
        std::cout << "请求数据有未知错误!" << std::endl;
        return "NULL";
    }

}

std::string Functions::processCidAndGetMid(const std::string& cid) {
    // 构建GET请求URL
    std::string url = SERVER_IP + "/get_multi_id_from_cid?cid=" + cid;

    // 发送GET请求并解析JSON数据
    Json::Value response = send_get_request(url);       
    // 在此处处理 JSON 数据并返回 multi_id
    /*std::string err_no = response["err_no"].asString(); //提取错误码,如1则报错
    if (err_no == "1") {
        std::cout << "未查询到该cid相应mid!" << std::endl;
        return "NULL";
    }
    else if (err_no == "0") {
        Json::Value mid = response["multi_id"];
        std::string Mid = jsonToString(mid);
        return Mid;
    }
    else {
        std::cout << "请求数据有未知错误!" << std::endl;
        return "NULL";
    }*/
    Json::Value mid = response["multi_id"];
    std::string Mid = jsonToString(mid);
    return Mid;
}

std::string Functions::processRidAndGetMid(const std::string& rid) {
    // 构建GET请求URL
    std::string url = SERVER_IP + "/get_multi_id_from_route_id?route_id=" + rid;

    // 发送GET请求并解析JSON数据
    Json::Value response = send_get_request(url);       //没写完,需要处理返回的json格式response,根据返回值判断是否成功并提取出multi_id
    // 在此处处理 JSON 数据并返回 multi_id


    /*std::string err_no = response["err_no"].asString(); //提取错误码,如1则报错
    if (err_no == "1") {
        std::cout << "未查询到该rid相应mid!" << std::endl;
        return "NULL";
    }
    else if (err_no == "0") {
        Json::Value mid = response["multi_id"];
        std::string Mid = jsonToString(mid);
        return Mid;
    }
    else {
        std::cout << "请求数据有未知错误!" << std::endl;
        return "NULL";
    }*/
    Json::Value mid = response["multi_id"];
    std::string Mid = jsonToString(mid);
    return Mid;
}

std::string Functions::calculateMD5Hash(const std::string& jsonStr) {
    

    
    std::string jsonString = jsonStr;

    // Calculate the MD5 hash
    unsigned char digest[MD5_DIGEST_LENGTH];
    MD5(reinterpret_cast<const unsigned char*>(jsonString.c_str()), jsonString.size(), digest);

    // Convert the binary hash to hexadecimal string
    char md5String[33];
    for (int i = 0; i < 16; i++) {
        snprintf(&md5String[i * 2], sizeof(md5String) - i * 2, "%02x", (unsigned int)digest[i]);
    }
    md5String[32] = '\0';

    return md5String;
}

std::string Functions::extractJsonData(const std::string& requestData)  //这个函数在分割字符串的时候有一个潜在问题，就是多重{}嵌套的时候可能会取的不全???
{
    size_t jsonStart = requestData.find("{");
    if (jsonStart != std::string::npos) {
        size_t jsonEnd = requestData.rfind("}");
        if (jsonEnd != std::string::npos && jsonEnd > jsonStart) {
            return requestData.substr(jsonStart, jsonEnd - jsonStart + 1);
        }
    }
    return "";
}

void Functions::URLEncode(std::string& str) {
    size_t pos;

    // 移除换行符 (\n)
    while ((pos = str.find('\n')) != std::string::npos) {
        str.erase(pos, 1);
    }

    // 移除制表符 (\t)
    while ((pos = str.find('\t')) != std::string::npos) {
        str.erase(pos, 1);
    }

    // 替换双引号 (") 为 %22
    while ((pos = str.find('"')) != std::string::npos) {
        str[pos] = '%';
        str.insert(pos + 1, "22");
    }

    //去除json字符串冒号两边出现的不明空格 此处去除了所有空格
    str.erase(std::remove(str.begin(), str.end(), ' '), str.end());
}

void Functions::ipv6_to_str_unexpanded(char *str, const struct in6_addr *addr) {
   sprintf(str, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
                 (int)addr->s6_addr[0], (int)addr->s6_addr[1],
                 (int)addr->s6_addr[2], (int)addr->s6_addr[3],
                 (int)addr->s6_addr[4], (int)addr->s6_addr[5],
                 (int)addr->s6_addr[6], (int)addr->s6_addr[7],
                 (int)addr->s6_addr[8], (int)addr->s6_addr[9],
                 (int)addr->s6_addr[10], (int)addr->s6_addr[11],
                 (int)addr->s6_addr[12], (int)addr->s6_addr[13],
                 (int)addr->s6_addr[14], (int)addr->s6_addr[15]);
}

void Functions::send_router_addr()
{
    
    CURL* curl;
    CURLcode res;
    std::string response;
    std::string url = SERVER_IP + "/store_sonic_router";
    curl = curl_easy_init();
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        curl_easy_setopt(curl, CURLOPT_POST, 1L);
        struct curl_slist* headers = NULL;
        headers = curl_slist_append(headers, "Content-Type: application/json");
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, my_write_callback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);
        

        struct ifaddrs* ifaddr;
        struct ifaddrs* ifa;
        getifaddrs(&ifaddr);
        for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
        {
            

            std::string ifname = ifa->ifa_name;
            if (    (ifname.find("docker") == std::string::npos)
                    && (ifname.find("Loop") == std::string::npos)
                    && (ifname.find("bridge") == std::string::npos)
                    && (ifname.find("dummy") == std::string::npos)
                    && ifa->ifa_addr 
                    && ifa->ifa_addr->sa_family == AF_INET6
                )
            {
                
                char ipv6AddressStr[INET6_ADDRSTRLEN];
                Functions::ipv6_to_str_unexpanded(ipv6AddressStr, &((struct sockaddr_in6*)ifa->ifa_addr)->sin6_addr);
                if(std::strncmp(ipv6AddressStr, "fe80", 4) == 0)
                {
                    continue;
                }
                std::string v6addr = ipv6AddressStr;
                
                Json::Value JsonData;
                JsonData["IPv6Addr"] = v6addr;
                JsonData["Router"] = HOST_NAME;
                std::string jsonValue = JsonData.toStyledString();
                curl_easy_setopt(curl, CURLOPT_POSTFIELDS, NULL);
                curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonValue.c_str());
                //test
                std::cout << "发送router数据:" << jsonValue << std::endl;   
                res = curl_easy_perform(curl);
                std::cout << "发送完成" << std::endl; 
                if (res != CURLE_OK) {
                    std::cout << "in error" << std::endl;
                    std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
                }
                std::cout << response << std::endl;   
                
            }//if
        }//for

        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
    
    }//if(curl)

}// send_router_addr()


int Functions::getCache(const std::string &service_id)
{
    if(service_id == "00000000" || service_id == "00000001" || service_id == "00101001" || service_id == "00101010" || service_id == "01001100"
     || service_id == "01001110" || service_id == "01100000" || service_id == "01100010")
        return 1;
    return 0;
}

int Functions::getCheck(const std::string &service_id)
{
    if(service_id == "00000000" || service_id == "00000001" || service_id == "00101001" || service_id == "00101010" || service_id == "01001100"
     || service_id == "01001110" || service_id == "01100000" || service_id == "01100010")
        return 1;
    return 0;
}
